<?php
// +----------------------------------------------------------------------
// | ThinkCMF [ WE CAN DO IT MORE SIMPLE ]
// +----------------------------------------------------------------------
// | Copyright (c) 2013-2017 http://www.thinkcmf.com All rights reserved.
// +----------------------------------------------------------------------
// | Author: Dean <zxxjjforever@163.com>
// +----------------------------------------------------------------------
namespace api\wxapp\controller;

use cmf\controller\RestBaseController;
use api\wxapp\model\OrderModel;
use api\wxapp\model\UserModel;
use api\wxapp\model\UserStudentModel;
use wxapp\aes\Wxpay;
use wxapp\aes\WXBizDataCrypt;
use think\Db;
use think\Validate;

class UserController extends RestBaseController
{
    protected $postModel;
    public function __construct(UserModel $postModel)
    {
        parent::__construct();
        $this->postModel = $postModel;
    }
    public function getUser(){
        $userId = $this->getUserId(); 
        $model = new UserModel();
        $where = array(
            'id' => $userId            
        );
        $list = $model->where($where)->find();
        $this->success('请求成功',$list);  
    }
    // 获取用户信息
    public function getUserStudents()
    {
        $userId = $this->getUserId(); 
        $model = new UserStudentModel();
        $where = array(
            'user_id' => $userId,
            'delete_time' => 0
        );
        $list = $model->where($where)->select();
        $this->success('请求成功',$list);      
    }

    // 获取用户信息
    public function addUserStudents()
    {
        $data = $this->request->param();
        $userId = $this->getUserId(); 
        $model = new UserStudentModel();       
        $data['user_id'] = $userId;        
        $list = $model->allowField(true)->isUpdate(false)->save($data);
        $this->success('请求成功',$list);      
    }
    // 修改用户信息
    public function editUserStudents()
    {
        $data = $this->request->param();
        $userId = $this->getUserId(); 
        $model = new UserStudentModel(); 
        $list = $model->allowField(true)->isUpdate(true)->save($data);
        $this->success('请求成功',$list);      
    }

     // 获取用户信息
     public function delUserStudents()
     {
         $userId = $this->getUserId(); 
         $model = new UserStudentModel();     
         $data = $this->request->param();
         $data['delete_time'] = time();
         $list = $model->allowField(true)->isUpdate(true)->save($data);
         $this->success('请求成功',$list);      
     }

     public function getStudentsInfo()
    {
        $data = $this->request->param();        
        $model = new UserStudentModel();       
        $where = array(
            'id' => $data['id'],
            'delete_time' => 0
        );
        $list = $model->where($where)->find();
        $this->success('请求成功',$list);      
    }

    public function getOrders(){
        $userId = $this->getUserId(); 
        $model = new OrderModel();
        $list = $model->with(['user','course','student'])->where('user_id',$userId)->order('id', 'desc')->select();        
        $this->success('请求成功',$list);      
    }

    public function addOrder(){
        $validate = new Validate([
            'course_id'           => 'require',              
            'seat'                 => 'require',
            'student_id'                 => 'require'        
        ]);
        $validate->message([
            'course_id.require'           => '缺少参数course_id!',  
            'seat.require'           => '缺少参数seat!',     
            'student_id.require'           => '缺少参数student_id!',  
        ]);

        $data = $this->request->param();
        if (!$validate->check($data)) {
            $this->error($validate->getError());
        }
        $timestamp = time();
        
        
        $seat_status =Db::name('order')->where("course_id={$data['course_id']} and seat={$data['seat']} and (({$timestamp} - create_time <= 900 and pay_status != 3) or  pay_status = 1)")->find();    
        if ($seat_status) {
            $this->error("添加失败，座位已被选或订单超时");
        }
        

        $userId = $this ->getUserId();
       
        if($userId){         
            $student =  Db::name('user_student')->where('id',$data['student_id'])->find();
            $user = Db::name('user')->where('id',$userId)->find();
            $row = Db::name('school_course')->where('id',$data['course_id'])->find();
            if($row['num'] - $row['order_count'] <= 0){
                $this->error("添加失败，报名人数已满");
            }
            $model = new OrderModel();
            $data['user_id'] = $userId;
            $data['order_no'] = $this -> getOrderNo();     
            $data['price'] = $row['price'];   
            $data['student_name'] = $student['name'];
            $data['parent_name'] = $user['user_nickname'];
            $data['current_school'] = $student['current_school'];
            $data['phone'] = $student['phone'];
            $result =  $model->allowField(true)->isUpdate(false)->save($data);
            if($result > 0){
                $requestData = array(
                    'appid' => 'wx22bd817e9339f253',
                    'mch_id' => '1519151931',
                    'nonce_str' => self::getNonceStr(),
                    'body' => $row['title'],
                    'out_trade_no' => $data['order_no'],
                    'total_fee' => $row['price'] * 100,
                    'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],
                    'notify_url' => 'https://sng.tsletu.com/api/wxapp/pay_notice/notice',
                    'trade_type' => 'JSAPI',
                    'openid' => $this->user['openid']
                );
                $requestData['sign'] = $this->MakeSign($requestData);                
                $wxPay = Wxpay::unifiedOrder($requestData);
                $result = Wxpay::FromXml($wxPay);
               
                if($result['return_code'] == 'FAIL'){
                    $this->error('调用失败',$result);
                }
                $data = array(
                    'appId' => 'wx22bd817e9339f253',
                    'timeStamp' => time(),
                    'nonceStr' => self::getNonceStr(),
                    'package' => 'prepay_id=' . $result['prepay_id'],
                    'signType' => 'MD5'
                );
                $data['paySign'] = $this->MakeSign($data); 
                $this->success('调用成功',$data);                
            }        
        }
        return $this->error('下单失败！');       
    }
    
    public function pay(){
        
        $data = $this->request->param();
        $userId = $this ->getUserId();
       
        if($userId){
            $orderinfo =Db::name('order')->where('id',$data['id'])->find();    

            $timestamp = time();
           
            $seat_status =Db::name('order')->where("id!={$orderinfo['id']} and course_id={$orderinfo['course_id']} and seat={$orderinfo['seat']} and ({$timestamp} - create_time <= 900 or  pay_status = 1)")->find();    
            if ($seat_status) {
                $this->error("添加失败，座位已被选或订单超时");
            }
           
            $row = Db::name('school_course')->where('id',$orderinfo['course_id'])->find();
            if($row['num'] - $row['order_count'] <= 0){
                $this->error("添加失败，报名人数已满");
            }
            $requestData = array(
                'appid' => 'wx22bd817e9339f253',
                'mch_id' => '1519151931',
                'nonce_str' => self::getNonceStr(),
                'body' => $row['title'],
                'out_trade_no' => $orderinfo['order_no'],
                'total_fee' => $orderinfo['price'] * 100,
                'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],
                'notify_url' => 'https://sng.tsletu.com/api/wxapp/pay_notice/notice',
                'trade_type' => 'JSAPI',
                'openid' => $this->user['openid']
            );
            $requestData['sign'] = $this->MakeSign($requestData);                
            $wxPay = Wxpay::unifiedOrder($requestData);
            $result = Wxpay::FromXml($wxPay);
            
            if($result['return_code'] == 'FAIL'){
                $this->error('调用失败',$result);
            }
            
            $data = array(
                'appId' => 'wx22bd817e9339f253',
                'timeStamp' => time(),
                'nonceStr' => self::getNonceStr(),
                'package' => 'prepay_id=' . $result['prepay_id'],
                'signType' => 'MD5'
            );
            $data['paySign'] = $this->MakeSign($data); 
            $this->success('调用成功',$data);           
        }
        return $this->error('下单失败！');       
    }

    public function getOrderNo(){
        $no = '';      
        while(true){            
            $no = date('Ymd').substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
            $row = Db::name('order')->where('order_no',$no)->find();
            if(!$row){
                break;
            }
        }
        return $no;        
    }

    public function getSchoolNo(){
        $no = '';      
        while(true){            
            $no = substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
            $row = Db::name('user_student')->where('school_no',$no)->find();
            if(!$row){
                break;
            }
        }
        return $no;        
    }
    //绑定手机号
    public function bindPhone(){
        $validate = new Validate([
            'code'           => 'require',
            'encrypted_data' => 'require',
            'iv'             => 'require',            
        ]);

        $validate->message([
            'code.require'           => '缺少参数code!',
            'encrypted_data.require' => '缺少参数encrypted_data!',
            'iv.require'             => '缺少参数iv!',            
        ]);

        $data = $this->request->param();
        if (!$validate->check($data)) {
            $this->error($validate->getError());
        }

        $code          = $data['code'];
        $wxappSettings = cmf_get_option('wxapp_settings');

        $appId = $this->request->header('XX-Wxapp-AppId');
        if (empty($appId)) {
            if (empty($wxappSettings['default'])) {
                $this->error('没有设置默认小程序！');
            } else {
                $defaultWxapp = $wxappSettings['default'];
                $appId        = $defaultWxapp['app_id'];
                $appSecret    = $defaultWxapp['app_secret'];
            }
        } else {
            if (empty($wxappSettings['wxapps'][$appId])) {
                $this->error('小程序设置不存在！');
            } else {
                $appId     = $wxappSettings['wxapps'][$appId]['app_id'];
                $appSecret = $wxappSettings['wxapps'][$appId]['app_secret'];
            }
        }


        $response = cmf_curl_get("https://api.weixin.qq.com/sns/jscode2session?appid=$appId&secret=$appSecret&js_code=$code&grant_type=authorization_code");

        $response = json_decode($response, true);
        if (!empty($response['errcode'])) {
            $this->error('操作失败!',$response);
        }

        $openid     = $response['openid'];
        $sessionKey = $response['session_key'];

        $pc      = new WXBizDataCrypt($appId, $sessionKey);
        $errCode = $pc->decryptData($data['encrypted_data'], $data['iv'], $wxUserData);

        if ($errCode != 0) {
            $this->error('操作失败!');
        }
        $userId = $this->getUserId(); 
        Db::name("user")
                ->where('id', $userId)                
                ->update(['mobile' => $wxUserData['phoneNumber']]);
        return  $this->success("绑定成功!", $wxUserData);
    }
    /**
	 * 
	 * 产生随机字符串，不长于32位
	 * @param int $length
	 * @return 产生的随机字符串
	 */
	public static function getNonceStr($length = 32) 
	{
		$chars = "abcdefghijklmnopqrstuvwxyz0123456789";  
		$str ="";
		for ( $i = 0; $i < $length; $i++ )  {  
			$str .= substr($chars, mt_rand(0, strlen($chars)-1), 1);  
		} 
		return $str;
    }
    /**
	 * 格式化参数格式化成url参数
	 */
	public function ToUrlParams($data)
	{
		$buff = "";
		foreach ($data as $k => $v)
		{
			if($k != "sign" && $v != "" && !is_array($v)){
				$buff .= $k . "=" . $v . "&";
			}
		}
		
		$buff = trim($buff, "&");
		return $buff;
	}
	
	/**
	 * 生成签名
	 * @return 签名，本函数不覆盖sign成员变量，如要设置签名需要调用SetSign方法赋值
	 */
	public function MakeSign($data)
	{
        error_reporting(0);
		//签名步骤一：按字典序排序参数
		ksort($data);
		$string = $this->ToUrlParams($data);		
		//签名步骤二：在string后加入KEY
		
		$string = $string . "&key=2a336dc09120317722a8366b35051884";
		//签名步骤三：MD5加密
		$string = md5($string);
		//签名步骤四：所有字符转为大写
		$result = strtoupper($string);
		return $result;
    }
    
}
